package com.gwclh.personnel.controller;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gwclh.personnel.bean.ResultVo;
import com.gwclh.personnel.common.constants.UserConstants;
import com.gwclh.personnel.entity.User;
import com.gwclh.personnel.service.IUserService;
import com.gwclh.personnel.shiro.AccountProfile;
import com.gwclh.personnel.utils.JwtUtils;
import com.gwclh.personnel.utils.ShiroUtil;
import com.gwclh.personnel.vo.LoginVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@Api(tags = "登录相关逻辑")
@Validated
@Slf4j
public class LoginController {

    @Autowired
    IUserService userService;
    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    RedisTemplate redisTemplate;

    @PostMapping("/login")
    @ApiOperation(value = "用户登录")
    @ApiImplicitParam(value = "登录vo",name = "LoginVo",dataType = "LoginVo",paramType = "query")
    public ResultVo login(@Validated  @RequestBody LoginVo loginVo){
        // 1. 验证验证码
        String key = loginVo.getKey();
        String code = loginVo.getCode();

        String redisCode = (String) redisTemplate.opsForValue().get(UserConstants.CAPTCHA_REDIS_KEY+key);
        //1.1 判断redis是否有key的键
        Assert.isTrue(redisCode!=null,"验证码错误");
        //1.2 判断redisCode是否与code的相等
        Assert.isTrue(redisCode.equals(code),"验证码错误");


        // 2. 登录操作
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username",loginVo.getUsername());
        User user = userService.getOne(userQueryWrapper);
        Assert.notNull(user,"账号密码错误");
        Assert.isTrue(user.getStatus(),"该账户已被冻结");
        Assert.isTrue(user.getPassword().equals(SecureUtil.md5(loginVo.getPassword())),"账号密码错误");

        // 3. 验证通过，生成token,返回数据
        String jwt = jwtUtils.generateToken(user.getId());
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("id",user.getId());
        resultMap.put("username", user.getUsername());
        resultMap.put("avatar", user.getAvatar());
        resultMap.put("token", jwt);
        resultMap.put("role", user.getRole());

        // 删除redis中的键
        redisTemplate.delete(UserConstants.CAPTCHA_REDIS_KEY+key);
        return ResultVo.success(resultMap);
    }



    @GetMapping("/logout")
    @ApiOperation(value = "注销接口", notes = "用户退出登录后需要调用该接口，清除redis缓存")
    public ResultVo logout() {
        Integer id = ShiroUtil.getProfile().getId();
        if (redisTemplate.hasKey(UserConstants.SHIRO_USER_REDIS_KEY + id)) {
            redisTemplate.delete(UserConstants.SHIRO_USER_REDIS_KEY + id);
        }
        SecurityUtils.getSubject().logout();
        return ResultVo.success();
    }

    @GetMapping("/captcha")
    @ApiOperation(value = "生成图灵验证码,base64")
    public ResultVo getCaptcha(){
        Map<String,Object> resultMap = new HashMap<>();
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        String image = lineCaptcha.getImageBase64();
        String code = lineCaptcha.getCode();
        // 生成唯一key
        String randomToken = IdUtil.simpleUUID();
        redisTemplate.opsForValue().set(UserConstants.CAPTCHA_REDIS_KEY+randomToken,code,5, TimeUnit.MINUTES);

        resultMap.put("captcha","data:image/png;base64,"+image);
        resultMap.put("key",randomToken);
        return ResultVo.success(resultMap);
    }

    @GetMapping("/token")
    @ApiOperation(value = "根据token获取用户信息")
    public ResultVo getUserByToken(){
        AccountProfile accountProfile = ShiroUtil.getProfile();
        return ResultVo.success(accountProfile);
    }

}
